from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect
from web.forms.issues import IssuesModelForm, IssuesReplyModelForm, InviteModelForm
from web import models
from utils.pagination import Pagination
from django.views.decorators.csrf import csrf_exempt
from django.utils.safestring import mark_safe
import json, datetime
from utils.encrypt import uid
from django.urls import reverse

# 复选框 和 foreign key
class CheckFilter:
    def __init__(self, name, choices_list, request):
        self.name = name
        self.choices_list = choices_list
        self.request = request

    def __iter__(self):
        for item in self.choices_list:
            key = str(item[0])
            text = item[1]
            ck = ""
            # 如果当前用户请求的URL中的status和当前循环的key相等，则让ck = "checked"
            value_list = self.request.GET.getlist(self.name)
            if key in value_list:  # 如果每次循环的key值在筛选条件中，则让其处于选中状态
                ck = "checked"
                value_list.remove(key)  # 再次点击取消选中
            else:
                # 每次进来对value_list进行循环,如果key在value_list中，则将value_list中的ｋｅｙ去除，如果不再，则进行添加
                value_list.append(key)

            # 为a标签生成url
            # 在当前的URL的基础上去增加一项
            print("value_list:", key, value_list)
            query_dict = self.request.GET.copy()  # 拷贝一份
            query_dict._mutable = True  # 让其可变
            query_dict.setlist(self.name, value_list)  # 设置参数
            # 对page的url进行重置,默认页码为1
            if "page" in query_dict:
                query_dict.pop("page")
            # 对url中后边的？的处理
            query_param = query_dict.urlencode()  # 参数
            print("query_param", query_param)
            if query_param:  # 带参数的话就拼接
                url = "{}?{}".format(self.request.path_info, query_param)  # 拼接url
            else:
                url = self.request.path_info  # 不带参数就是根url

            html = "<a class='cell' href='{url}'><input type='checkbox' {ck} /><label>{text}</label></a>".format(
                url=url, ck=ck, text=text)

            yield mark_safe(html)

# 下拉框
class SelectFilter:
    def __init__(self, name, choices_list, request):
        self.name = name
        self.choices_list = choices_list
        self.request = request

    def __iter__(self):
        yield mark_safe("<select class='c1' multiple='multiple' style='width:100%' > ")
        for item in self.choices_list:
            key = str(item[0])
            text = item[1]
            value_list = self.request.GET.getlist(self.name)
            print(value_list)
            selected = ""
            if key in value_list:
                selected = "selected"
                value_list.remove(key)
            else:
                value_list.append(key)
            query_dict = self.request.GET.copy()
            query_dict._mutable = True
            query_dict.setlist(self.name, value_list)
            if "page" in query_dict:
                query_dict.pop("page")

            query_params = query_dict.urlencode()
            if query_params:
                url = "{}?{}".format(self.request.path_info, query_params)
            else:
                url = self.request.path_info
            print(url)
            html = "<option value='{url}'{selected}>{text}</option>".format(url=url, selected=selected, text=text)
            yield mark_safe(html)
        yield mark_safe("</select>")


def issues(request, project_id):
    if request.method == "GET":
        # 更具URL做筛选，筛选条件（根据用户传过来的参数实现）
        # ？status=1&status=2&issues_type=1 ,相同的字段代表或，不同的字段表示且
        # 允许过滤的字段
        allow_filter_name = ["issues_type", "status", "priority", "assign", "attention"]
        condition = {}  # 构造一个条件字典
        for name in allow_filter_name:
            value_list = request.GET.getlist(name)  # [1,2] 或 [1,]
            if not value_list:
                continue
            condition["{}__in".format(name)] = value_list
            """
            condition = {
                "status__in":[1,2],
                "priority__in":[1,],
                "issues_type__in":[1,],
            }
            """

        queryset = models.Issues.objects.filter(project_id=project_id).filter(**condition)

        page_object = Pagination(
            current_page=request.GET.get("page"),
            all_count=queryset.count(),
            base_url=request.path_info,
            query_params=request.GET,

        )
        issue_object_list = queryset[page_object.start:page_object.end]
        page_html = page_object.page_html()
        form = IssuesModelForm(request)
        invite_form = InviteModelForm()
        project_issues_type = models.IssueType.objects.filter(project_id=project_id).values_list("id", "title")  # 项目的问题类型
        project_total_user = [(request.tracer.project.creator_id, request.tracer.project.creator.username),]   # 创建者
        project_join_user = models.ProjectUser.objects.filter(project_id=project_id).values_list("user_id", "user__username")
        project_total_user.extend(project_join_user)

        return render(request, "issues.html", {"form": form,
                                               "invite_form": invite_form,
                                               "issue_object_list": issue_object_list,
                                               "page_html": page_html,
                                               "status_filter": CheckFilter("status", models.Issues.status_choices,
                                                                            request),
                                               "priority_filter": CheckFilter("priority",
                                                                              models.Issues.priority_choices,
                                                                              request),
                                               "issues_type_filter": CheckFilter("issues_type", project_issues_type, request),
                                                "assign_filter": SelectFilter("assign", project_total_user, request),
                                               "attention_filter": SelectFilter("attention", project_total_user, request),
                                               })

    form = IssuesModelForm(request, data=request.POST)
    if form.is_valid():
        form.instance.project = request.tracer.project
        form.instance.creator = request.tracer.user
        form.save()
        return JsonResponse({"status": True, })

    return JsonResponse({"status": False, "error": form.errors})


def issues_detail(request, project_id, issue_id):
    """问题详情"""

    issue_object = models.Issues.objects.filter(project_id=project_id, id=issue_id).first()
    form = IssuesModelForm(request, instance=issue_object)

    return render(request, "issues_detail.html", {"form": form, "issue_object": issue_object})


@csrf_exempt
def issues_record(request, project_id, issue_id):
    """问题记录"""
    if request.method == 'GET':
        reply_list = models.IssuesReply.objects.filter(issues_id=issue_id, issues__project=request.tracer.project)
        data_list = []
        print(reply_list)
        for row in reply_list:
            data = {
                "id": row.id,
                "reply_type": row.get_reply_type_display(),
                "content": row.content,
                "creator": row.creator.username,
                "create_time": row.create_time.strftime("%Y-%m-%d %H:%M"),
                "parent_id": row.reply_id,
            }
            data_list.append(data)

        return JsonResponse({"status": True, "data": data_list})

    form = IssuesReplyModelForm(data=request.POST)
    # print(request.POST)
    if form.is_valid():
        form.instance.creator = request.tracer.user
        form.instance.reply_type = 2
        form.instance.issues_id = issue_id
        instance = form.save()
        info = {
            "id": instance.id,
            "reply_type": instance.get_reply_type_display(),
            "content": instance.content,
            "creator": instance.creator.username,
            "create_time": instance.create_time.strftime("%Y-%m-%d %H:%M"),
            "parent_id": instance.reply_id,
        }
        return JsonResponse({"status": True, "data": info})
    return JsonResponse({"status": False, "error": form.errors})


@csrf_exempt
def issues_change(request, project_id, issue_id):
    """问题更新"""
    issues_object = models.Issues.objects.filter(id=issue_id, project_id=project_id).first()
    post_dict = json.loads(request.body.decode("utf-8"))
    # print(post_dict)
    # {'name': 'status', 'value': '2'}, {'name': 'issues_type', 'value': '2'}
    name = post_dict.get("name")
    value = post_dict.get("value")
    field_object = models.Issues._meta.get_field(name)

    def create_reply_record(content):
        """创建一条记录"""
        change_obj = models.IssuesReply.objects.create(
            reply_type=1,
            issues=issues_object,
            content=change_msg,
            creator=request.tracer.user,

        )
        info = {
            "id": change_obj.id,
            "reply_type": change_obj.get_reply_type_display(),
            "content": change_obj.content,
            "creator": change_obj.creator.username,
            "create_time": change_obj.create_time.strftime("%Y-%m-%d %H:%M"),
            "parent_id": change_obj.reply_id,
        }
        return info

    # 1. 传递的值value为文本信息
    if name in ["subject", "desc", "start_date", "end_date"]:
        # 判断传递的value是否为空
        if not value:  # 如果传递的值为空
            if not field_object.null:  # 如果数据库的字段不能为空
                return JsonResponse({"status": False, "error": "您更新的字段不能为空"})
            setattr(issues_object, name, None)
            issues_object.save()
            change_msg = "{}字段更新为空".format(field_object.verbose_name)
        else:
            setattr(issues_object, name, value)
            issues_object.save()
            change_msg = "{}更新为了{}".format(field_object.verbose_name, value)

        # 然后创建一条问题变更记录
        return JsonResponse({"status": True, "data": create_reply_record(change_msg)})

    # 2. 传递的值value为Foreign Key  1、2、3、
    if name in ["issues_type", "module", "assign", "parent"]:
        if not value:
            if not field_object.null:
                return JsonResponse({"status": False, "error": "您更新的字段不能为空"})
            setattr(issues_object, name, None)
            issues_object.save()
            change_msg = "{}字段更新为空".format(field_object.verbose_name)

        else:  # 用户输入不为空
            # 对assign字段进行单独校验
            if name == "assign":
                # 1. 是否是项目创建者
                if value == str(request.tracer.project.creator_id):
                    instance = request.tracer.project.creator
                else:  # 2. 是否是项目参数者
                    project_user_object = models.ProjectUser.objects.filter(project_id=project_id,
                                                                            user_id=value).first()
                    if project_user_object:
                        instance = project_user_object.user
                    else:
                        instance = None
                if not instance:
                    return JsonResponse({"status": False, "error": "您选择的值不存在"})
                setattr(issues_object, name, instance)
                issues_object.save()
                change_msg = "{}更新为了{}".format(field_object.verbose_name, str(instance))
            else:
                # 判断条件：用户输入的值是自己的值
                instance = field_object.rel.model.objects.filter(id=value,
                                                                 project_id=project_id).first()  # 通过field_object.rel.model拿到外键指向的表对象
                if not instance:
                    return JsonResponse({"status": False, "error": "您选择的值不存在"})
                setattr(issues_object, name, instance)
                issues_object.save()
                change_msg = "{}更新为了{}".format(field_object.verbose_name, str(instance))  # str一下会触发instance的__str__方法

        return JsonResponse({"status": True, "data": create_reply_record(change_msg)})

    # 3. 传递的值value为choices
    if name in ["priority", "status", "mode"]:
        selected_text = None
        for key, text in field_object.choices:
            if str(key) == value:
                selected_text = text
        if not selected_text:
            return JsonResponse({"status": False, "error": "您选择的值不存在"})
        setattr(issues_object, name, value)
        issues_object.save()
        change_msg = "{}更新为了{}".format(field_object.verbose_name, selected_text)
        return JsonResponse({"status": True, "data": create_reply_record(change_msg)})

    # 4. M2M字段
    if name == "attention":
        # {"name":"attention","value":[1,2,3]}
        if not isinstance(value, list):
            return JsonResponse({"status": False, "error": "数据格式错误"})
        if not value:  # 如果列表中不存在值，将第三张表置为空
            issues_object.attention.set([])  # 找到第三张表
            issues_object.save()
            change_msg = "{}更新为了空".format(field_object.verbose_name)
        else:
            # 判断传过来的id是否是项目成员（创建者或参与者）
            # 获取当前项目的所有成员
            user_dict = {str(request.tracer.project.creator_id): request.tracer.project.creator.username, }
            project_user_list = models.ProjectUser.objects.filter(project_id=project_id)
            # 循环参与人员列表，将id 和 username放入user_dict
            for item in project_user_list:
                user_dict[str(item.user_id)] = item.user.username

            username_list = []
            for user_id in value:
                username = user_dict.get(str(user_id))
                if not username:
                    return JsonResponse({"status": False, "error": "用户不存在，请重新设置"})
                username_list.append(username)
            issues_object.attention.set(value)
            issues_object.save()
            change_msg = "{}更新为{}".format(field_object.verbose_name, ",".join(username_list))

        return JsonResponse({"status": True, "data": create_reply_record(change_msg)})

    return JsonResponse({"status": False, "error": "数据错误"})


def invite_url(request, project_id):
    """生成邀请码"""

    print(request.POST)
    form = InviteModelForm(data=request.POST)
    if form.is_valid():
        """
        1、创建随机的邀请码
        2、验证码保存到数据库
        3、限制：只有创建者才能邀请
        """
        # 如果当前用户不是项目的创建者
        if request.tracer.user != request.tracer.project.creator:
            form.add_error("period", "无权创建邀请码")
            return JsonResponse({"status": False, "error": form.errors})

        # 生成随机的邀请码
        random_invite_code = uid(request.tracer.user.mobile_phone)
        # 初始化其他字段
        form.instance.creator = request.tracer.user
        form.instance.project = request.tracer.project
        form.instance.code = random_invite_code
        # 保存到数据库
        form.save()
        # 将验证码返回给前端，前端的页面展示出来
        # url的拼接
        url = "{scheme}://{host}{path}".format(
            scheme=request.scheme,
            host=request.get_host(),
            path=reverse("web:invite_join", kwargs=({"code": random_invite_code}))  # 反向生成的url,将邀请码传入
        )
        return JsonResponse({"status": True, "data": url})

    return JsonResponse({"status": False, "error": form.errors})


def invite_join(request, code):
    """ 访问邀请码 """
    # 通过邀请码去数据库查到邀请链接的对象
    invite_object = models.ProjectInvite.objects.filter(code=code).first()
    # 1. 判断邀请码是否存在
    if not invite_object:
        return render(request, "invite_join.html", {"error": "邀请码不存在"})
    # 2、判断当前用户是否是项目的创建者
    if invite_object.project.creator == request.tracer.user:
        return render(request, "invite_join.html", {"error": "创建者无需再添加"})
    # 3、判断当前用户是否已经加入了项目
    exists = models.ProjectUser.objects.filter(project=invite_object.project, user=request.tracer.user).exists()
    if exists:
        return render(request, "invite_join.html", {"error": "已加入项目，无需再加入项目"})

    # 4、 判断项目设置的最多允许的成员是否超标
    # 允许项目最大的成员数
    # max_member = request.tracer.price_policy.project_member
    #v 需要判断是否过期，如果过期则使用免费的额度
    # 找到当前项目的创建者所有的交易记录，并排序找到最近一次的交易记录
    max_transaction = models.Transaction.objects.filter(user=invite_object.project.creator).order_by("-id").first()
    current_datetime = datetime.datetime.now()
    # 如果交易记录的价格策略显示，category为1,则表示是免费的
    if max_transaction.price_policy.category == 1:
            max_member = max_transaction.price_policy.project_member
    else:
        if max_transaction.end_datetime < current_datetime:  # 过期
            free_object = models.PricePolicy.objects.filter(category=1).first()
            max_member = free_object.project_member
        else:
            max_member = max_transaction.price_policy.project_member


    # 当前设置的成员数
    current_member = invite_object.count
    if current_member > max_member:
        return render(request, "invite_join.html", {"error": "项目设置的成员超限，请升级套餐"})
    # 5、邀请码是否过期的判断

    # 有效截止时间
    limit_datetime = invite_object.create_datetime + datetime.timedelta(minutes=invite_object.period)
    if current_datetime > limit_datetime:
        return render(request, "invite_join.html", {"error": "邀请码已过期"})

    # 6、 数量限制
    if invite_object.count:
        # 判断已使用的数量和允许最大限制
        if invite_object.user_count >= invite_object.count:
            return render(request, "invite_join.html", {"error": "邀请码数量已使用完"})
        # 已使用数量 + 1
        invite_object.user_count += 1
        invite_object.save()
        # 创建参与者
        models.ProjectUser.objects.create(user=request.tracer.user, project=invite_object.project)
        return render(request, "invite_join.html", {"project": invite_object.project})

    else:
        # 无数量限制
        # 创建参与者
        models.ProjectUser.objects.create(user=request.tracer.user, project=invite_object.project)
        # 项目参与者+1
        invite_object.project.join_count += 1
        invite_object.project.save()
        return render(request, "invite_join.html", {"project": invite_object.project})






